package com.appspot.showup_app.showup;

import android.accounts.AccountManager;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.appspot.showup_app.showup.tasks.GetUpdatesTask;
import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.android.gms.common.AccountPicker;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.client.util.Strings;
import com.mixpanel.android.mpmetrics.MixpanelAPI;

import android.accounts.Account;

import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


public class MainActivity extends Activity {

    private static final String LOG_TAG = "MainActivity";
    private static final int ACTIVITY_RESULT_FROM_ACCOUNT_SELECTION = 2222;
    private static final String PREF_ACCOUNT_NAME = "pref_account_name1";
    private static final String TAG = "Showup";
    private static final int EDIT_BUSINESS_INFO = 1;
    private static final int REQUEST_AUTHORIZATION = 2;
    SharedPreferences settings;
    private AuthorizationCheckTask mAuthTask;
    private GoogleAccountCredential credential;
    private String accountName;

    View btnSignIn;
    ProgressBar loading;
    MixpanelAPI mMixpanel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);

        setContentView(R.layout.activity_main);


        mMixpanel = MixpanelAPI.getInstance(this, "80f52299b10b5a5abcbcf8ac3fed0b07");
        mMixpanel.track("App loaded", null);

        btnSignIn = findViewById(R.id.btn_sign_in);
        loading = (ProgressBar)findViewById(R.id.loading);

        // Prevent the keyboard from being visible upon startup.
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

        settings = getSharedPreferences(TAG, 0);

        btnSignIn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onClickSignIn();
            }
        });

        accountName = settings.getString(PREF_ACCOUNT_NAME, null);
        if (accountName != null) {
            btnSignIn.setVisibility(View.GONE);
            loading.setVisibility(View.VISIBLE);
            performAuthCheck(accountName);
        }
    }


    private void AuthorizationFinished() {
        GetUpdatesTask getUpdatesTask = new GetUpdatesTask(this) {
            @Override
            protected void onPostExecute(Boolean success) {
                if (success) {
                    if (settings.getString("pref_bi_name", null) != null) {
                        startActivity(new Intent(MainActivity.this, AgendaActivity.class));
                        finish();
                    }
                    else {
                        startActivityForResult(new Intent(MainActivity.this, EditBusinessInfoActivity.class), EDIT_BUSINESS_INFO);
                    }
                }
                else
                    Toast.makeText(MainActivity.this, "Error fetching updates", Toast.LENGTH_LONG).show();
            }
        };
        getUpdatesTask.execute((Void)null);
    }


    @Override
    protected void onDestroy() {
        mMixpanel.flush();
        super.onDestroy();
        if (mAuthTask != null) {
            mAuthTask.cancel(true);
            mAuthTask = null;
        }
    }

    public void performAuthCheck(String emailAccount) {
        // Cancel previously running tasks.
        if (mAuthTask != null) {
            try {
                mAuthTask.cancel(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        new AuthorizationCheckTask().execute(emailAccount);
    }

    class AuthorizationCheckTask extends AsyncTask<String, Integer, Boolean> {
        @Override
        protected Boolean doInBackground(String... emailAccounts) {
            Log.i(LOG_TAG, "Background task started.");

            if (!AppConstants.checkGooglePlayServicesAvailable(MainActivity.this)) {
                return false;
            }

            String emailAccount = emailAccounts[0];
            // Ensure only one task is running at a time.
            mAuthTask = this;

            // Ensure an email was selected.
            if (Strings.isNullOrEmpty(emailAccount)) {
                publishProgress(R.string.toast_no_google_account_selected);
                // Failure.
                return false;
            }

            Log.d(LOG_TAG, "Attempting to get AuthToken for account: " + emailAccount);

            try {
                // If the application has the appropriate access then a token will be retrieved, otherwise
                // an error will be thrown.
                String exchangeToken = null;
                if (!settings.getBoolean("HAS_ACCESS_TOKEN", false)) {
                    exchangeToken = getAccessToken(emailAccount);
                    if (exchangeToken == null)
                        return false;
                }

                credential = GoogleAccountCredential.usingAudience(MainActivity.this, AppConstants.AUDIENCE);
                credential.setSelectedAccountName(emailAccount);
                String accessToken = credential.getToken();

                Log.d(LOG_TAG, "AccessToken retrieved: " + accessToken);

                ApplicationData.getInstance().credential = credential;
                ApplicationData.getInstance().emailAccount = emailAccount;

                SharedPreferences.Editor editor = settings.edit();
                editor.putString(PREF_ACCOUNT_NAME, emailAccount);
                editor.commit();

                if (exchangeToken != null) {
                    Showup api = AppConstants.getApiServiceHandle(credential);
                    api.user().auth(exchangeToken).execute();
                    settings.edit().putBoolean("HAS_ACCESS_TOKEN", true).commit();

                }
                // Success.
                return true;
            } catch (GoogleAuthException unrecoverableException) {
                Log.e(LOG_TAG, "Exception checking OAuth2 authentication.", unrecoverableException);
                publishProgress(R.string.toast_exception_checking_authorization);
                // Failure.
                return false;
            } catch (IOException ioException) {
                Log.e(LOG_TAG, "Exception checking OAuth2 authentication.", ioException);
                publishProgress(R.string.toast_exception_checking_authorization);
                // Failure or cancel request.
                return false;
            }


        }

        private String getAccessToken(String emailAccount) {
            String scope = String.format("oauth2:server:client_id:%s:api_scope:%s",
                    AppConstants.WEB_CLIENT_ID,
                    TextUtils.join(" ", ShowupScopes.all()));
            try {
                String exchangeCode = GoogleAuthUtil.getToken(MainActivity.this, emailAccount, scope);
                ApplicationData.getInstance().exchangeCode = exchangeCode;
                return exchangeCode;

            } catch (UserRecoverableAuthException e) {
                accountName = emailAccount;
                startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
                return null;
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            } catch (Exception e) {
                return null;
            }
        }

        @Override
        protected void onProgressUpdate(Integer... stringIds) {
            // Toast only the most recent.
            Integer stringId = stringIds[0];
            Toast.makeText(MainActivity.this, stringId, Toast.LENGTH_SHORT).show();
        }

        @Override
        protected void onPreExecute() {
            mAuthTask = this;
        }

        @Override
        protected void onPostExecute(Boolean success) {
            if (success) {
                // Authorization check successful
                AuthorizationFinished();
            } else {
                // Authorization check unsuccessful
                btnSignIn.setVisibility(View.VISIBLE);
                ApplicationData.getInstance().emailAccount = null;
            }


            mAuthTask = null;
        }



        @Override
        protected void onCancelled() {
            mAuthTask = null;
        }
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode ==  REQUEST_AUTHORIZATION) {
            if (resultCode == Activity.RESULT_OK) {
                performAuthCheck(accountName);
            }
        }
        if (requestCode == ACTIVITY_RESULT_FROM_ACCOUNT_SELECTION && resultCode == RESULT_OK) {
            // This path indicates the account selection activity resulted in the user selecting a
            // Google account and clicking OK.

            // Set the selected account.
            accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);

            // Fire off the authorization check for this account and OAuth2 scopes.
            performAuthCheck(accountName);
        }
        else if (requestCode == EDIT_BUSINESS_INFO && resultCode == RESULT_OK) {
            startActivity(new Intent(MainActivity.this, AgendaActivity.class));
            finish();
        }
    }

    public void onClickSignIn() {
        // Check to see how many Google accounts are registered with the device.
        int googleAccounts = AppConstants.countGoogleAccounts(this);
        if (googleAccounts == -1) {
            // No accounts registered, nothing to do.
            Toast.makeText(this, R.string.toast_no_google_accounts_registered,
                    Toast.LENGTH_LONG).show();
        } else if (googleAccounts == 1) {
            // If only one account then select it.

            AccountManager am = AccountManager.get(this);
            Account[] accounts = am.getAccountsByType(GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
            if (accounts != null && accounts.length > 0) {
                // Select account and perform authorization check.
                performAuthCheck(accounts[0].name);
            }
        } else {
            // More than one Google Account is present, a chooser is necessary.

            // Reset selected account.
            // Invoke an {@code Intent} to allow the user to select a Google account.
            Intent accountSelector = AccountPicker.newChooseAccountIntent(null, null,
                    new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, false,
                    "Select the account to access the HelloEndpoints API.", null, null, null);
            startActivityForResult(accountSelector, ACTIVITY_RESULT_FROM_ACCOUNT_SELECTION);
        }

    }


}
